/*
 *@Type RandomAccessFileUtil.java
 * @Desc
 * @Author urmsone urmsone@163.com
 * @date 2024/6/13 02:58
 * @version
 */
package utils;

import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.nio.file.attribute.UserPrincipal;
import java.nio.file.attribute.UserPrincipalLookupService;
import java.nio.file.attribute.UserPrincipalNotFoundException;

public class RandomAccessFileUtil {

    private static final String RW_MODE = "rw";

    private static final String TEMP_ROOT = "D:"+File.separator;

    public static int write(String filePath, byte[] value) {
        RandomAccessFile file = null;
        long len = -1L;
        try {
            file = new RandomAccessFile(filePath, RW_MODE);
            len = file.length();
            file.seek(len);
            file.write(value);
            file.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (int)len;
    }

    public static void writeInt(String filePath, int value) throws IOException {

        RandomAccessFile file = null;
        long len = -1L;
        try {
            file = new RandomAccessFile(filePath, RW_MODE);
            //写之前先检测文件大小
            if (file.length() + value > Const.MAX_FILE_SIZE ){
                //文件超出范围 进行Rotate操作
                FileRotatorUtil.performRotate(file,filePath);
                file = new RandomAccessFile(filePath, RW_MODE);
                len = file.length();
                file.seek(len);
                file.writeInt(value);

            }else {
                //文件内存足够 进行写入操作
                len = file.length();
                file.seek(len);
                file.writeInt(value);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            file.close();
        }
    }

    public static void writeIntDirectly(String filePath, int value) throws IOException {

        RandomAccessFile file = null;
        long len = -1L;
        try {
            file = new RandomAccessFile(filePath, RW_MODE);
                len = file.length();
                file.seek(len);
                file.writeInt(value);

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            file.close();
        }
    }



    public static byte[] readByIndex(String filePath, int index, int len) {
        RandomAccessFile file = null;
        byte[] res = new byte[len];
        try {
            file = new RandomAccessFile(filePath, RW_MODE);
            file.seek((long)index);
            file.read(res, 0, len);
            return res;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                file.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    //不完全删除 修改类型type为RM
    public static void removeByIndex(String filePath, int index, int len) {
        Path targetPath = Paths.get(filePath);
        Path tempPath = null;
        File tempFile = null;

        try {

            byte[] dataBytes = readByIndex(filePath, index, len);
            String data = new String(dataBytes, StandardCharsets.UTF_8);
            data = data.replace("SET", "RM");
            byte[] newDataBytes = data.getBytes();

            try(RandomAccessFile file = new RandomAccessFile(filePath, RW_MODE)){
                if (index < 0 || len > file.length()) {
                    throw new IllegalArgumentException("Invalid range parameters");
                }
                // 创建临时文件
                Path path = Paths.get(TEMP_ROOT);
                Path tempDir = path.resolve("tmp_files");

                // 确保临时目录存在
                if (!Files.exists(tempDir)) {
                    Files.createDirectories(tempDir);
                }

                String tempFileName = "temp_" + System.nanoTime() + ".table";
                tempPath = tempDir.resolve(tempFileName);

                Files.createFile(tempPath);
                tempFile = tempPath.toFile();
                tempFile.deleteOnExit();
                RandomAccessFile tempRaf = new RandomAccessFile(tempFile, RW_MODE);
                try{
                    // 复制删除范围前的内容
                    if (index - 4 != 0){
                        copyBytes(file, tempRaf, 0,index - 4);
                    }

                    writeInt(tempPath.toString(), newDataBytes.length);
                    tempRaf.close();
                    int pos = RandomAccessFileUtil.write(tempPath.toString(), newDataBytes);
                    tempRaf = new RandomAccessFile(tempFile, RW_MODE);
                    tempRaf.seek(tempRaf.length());

                    // 跳过要删除的范围
                    file.seek(index + len );

                    // 复制删除范围后的内容
                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    while ((bytesRead = file.read(buffer)) != -1) {
                        tempRaf.write(buffer, 0, bytesRead);
                    }
                }finally {
                    tempRaf.close();
                }

            }catch (IOException e){
                e.printStackTrace();
            }

            Files.move(tempPath, targetPath, StandardCopyOption.REPLACE_EXISTING);


        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private static void copyBytes(RandomAccessFile source,
                                  RandomAccessFile dest,
                                  long start,
                                  long end) throws IOException {
        source.seek(start);
        long bytesToCopy = end - start;
        byte[] buffer = new byte[2048];

        while (bytesToCopy > 0) {
            int bytesRead = source.read(buffer, 0,
                    (int) Math.min(buffer.length, bytesToCopy));
            if (bytesRead == -1) break;

            dest.write(buffer, 0, bytesRead);
            bytesToCopy -= bytesRead;
        }
    }

    //完全删除

    public static void delteByIndex(String filePath, int index, int len) {
        Path targetPath = Paths.get(filePath);
        Path tempPath = null;
        File tempFile = null;

        try {
            try(RandomAccessFile file = new RandomAccessFile(filePath, RW_MODE)){
                if (index < 0 || len > file.length()) {
                    throw new IllegalArgumentException("Invalid range parameters");
                }
                // 创建临时文件
                Path path = Paths.get(TEMP_ROOT);
                Path tempDir = path.resolve("tmp_files");

                // 确保临时目录存在
                if (!Files.exists(tempDir)) {
                    Files.createDirectories(tempDir);
                }

                String tempFileName = "temp_" + System.nanoTime() + ".table";
                tempPath = tempDir.resolve(tempFileName);

                Files.createFile(tempPath);
                tempFile = tempPath.toFile();
                tempFile.deleteOnExit();
                RandomAccessFile tempRaf = new RandomAccessFile(tempFile, RW_MODE);
                try{
                    // 复制删除范围前的内容
                    if (index - 4 != 0){
                        copyBytes(file, tempRaf, 0,index - 4);
                    }

                    // 跳过要删除的范围
                    file.seek(index + len );

                    // 复制删除范围后的内容
                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    while ((bytesRead = file.read(buffer)) != -1) {
                        tempRaf.write(buffer, 0, bytesRead);
                    }
                }finally {
                    tempRaf.close();
                }

            }catch (IOException e){
                e.printStackTrace();
            }

            Files.move(tempPath, targetPath, StandardCopyOption.REPLACE_EXISTING);


        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}
